home *** CD-ROM | disk | FTP | other *** search
/ Chip 2002 March / Chip_2002-03_cd1.bin / zkuste / delphi / kompon / d3456 / EHS.ZIP / setup.exe / {app} / ehshelprouter.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  2001-03-25  |  13.7 KB  |  451 lines

  1. { THelpRouter
  2.  
  3.   Delphi 3/4/5/6 Implementation of HTML HELP
  4.  
  5.   ⌐ 2000-2001 EC Software. All rights reserved.
  6.  
  7.   This product and it's source code is protected by patents, copyright laws and
  8.   international copyright treaties, as well as other intellectual property
  9.   laws and treaties. The product is licensed, not sold.
  10.  
  11.   The source code and sample programs in this package or parts hereof
  12.   as well as the documentation shall not be copied, modified or redistributed
  13.   without permission, explicit or implied, of the author.
  14.  
  15.  
  16.   EMail: info@ec-software.com
  17.   Internet: http://www.ec-software.com
  18.  
  19.   Disclaimer of Warranty
  20.   ----------------------
  21.  
  22.   THIS SOFTWARE AND THE ACCOMPANYING FILES ARE PROVIDED "AS IS" AND
  23.   WITHOUT WARRANTIES OF ANY KIND WHETHER EXPRESSED OR IMPLIED.
  24.  
  25.   In no event shall the author be held liable for any damages whatsoever,
  26.   including without limitation, damages for loss of business profits,
  27.   business interruption, loss of business information, or any other loss
  28.   arising from the use or inability to use the software. }
  29.  
  30. unit ehshelprouter;
  31.  
  32. interface
  33.  
  34. uses
  35.   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  36.   Menus;
  37.  
  38. type
  39.   THelpType = (htWinhelp, htHTMLhelp, htMixedMode);
  40.   TShowType = (stDefault, stMain, stPopup);
  41.  
  42.   THtmlOption  = (hoSupportPopups, hoMixedMode);
  43.   THtmlOptions = set of THtmlOption;
  44.  
  45.   THelpRouter = class(TComponent)
  46.   private
  47.     fHelpType: THelpType;
  48.     fShowType: TShowType;
  49.     fAppOnHelp: THelpEvent;
  50.     fOnHelp: THelpEvent;
  51.     fHelpfile: string;
  52.     fCHMPopupTopics: string;
  53.     fValidateID: boolean;
  54.     fPP: TPoint;
  55.     function  CurrentForm: TForm;
  56.     function  OnRouteHelp(Command: Word; Data: Longint; var CallHelp: Boolean): Boolean;
  57.     function  FindHandle(var returnHelpFile: string): HWND;
  58.     procedure SetHelpType(value: THelpType);
  59.     function  ValidateHTMLID(link: string): string;
  60.   protected
  61.   public
  62.     constructor Create(AOwner: TComponent); override;
  63.     destructor  Destroy; override;
  64.     function    HTMLhelpInstalled: boolean;
  65.     function    HelpContent: boolean;
  66.     function    HelpKeyword(keyword: string): boolean;
  67.     function    HelpKLink(keyword: string): boolean;
  68.     function    HelpALink(keyword: string): boolean;
  69.     function    HelpJump(hfile, topicid: string): boolean;
  70.     function    HelpPopup(X,Y: integer; HelpContext: integer; text: string): boolean;
  71.   published
  72.     property HelpType: THelpType read fHelpType write SetHelpType;
  73.     property ShowType: TShowType read fShowType write fShowType default stDefault;
  74.     property Helpfile: string read fHelpfile write fHelpfile;
  75.     property CHMPopupTopics: string read fCHMPopupTopics write fCHMPopupTopics;
  76.     property OnHelp: THelpEvent read fOnHelp write fOnHelp;
  77.     property ValidateID: boolean read fValidateID write fValidateID;
  78.   end;
  79.  
  80. var
  81.    GLOBAL_HELPROUTER: THelpRouter;
  82.  
  83. implementation
  84.  
  85. uses ehshhapi;
  86.  
  87. var
  88.    aHH_AKLINK: THH_AKLINK;
  89.    aHH_POPUP: THH_POPUP;
  90.    aHelpHandle: HWND;
  91.    aKeyWord, aHelpFile: string;
  92.  
  93. function CheckRouterInstance: boolean;
  94. begin
  95.   result := false;
  96.   if GLOBAL_HELPROUTER <> NIL then raise Exception.Create('Multiple instances of THelpRouter are not allowed')
  97.   else result := true;
  98. end;
  99.  
  100. { --- THelpRouter --- }
  101.  
  102. constructor THelpRouter.Create(AOwner: TComponent);
  103. begin
  104.   inherited Create(AOwner);
  105.   if CheckRouterInstance and not (csDesigning in Componentstate) then
  106.   begin
  107.        fAppOnHelp := Application.onhelp;
  108.        Application.onhelp := OnRouteHelp;
  109.        GLOBAL_HELPROUTER := Self;
  110.   end;
  111.   fShowType := stDefault;
  112.   fCHMPopupTopics := 'CSHelp.txt';
  113. end;
  114.  
  115. destructor THelpRouter.Destroy;
  116. begin
  117.   if not (csDesigning in Componentstate) then
  118.   begin
  119.        if (Application.Handle <> 0) and (Application.HelpFile = '') then Application.HelpCommand(HELP_QUIT, 0);
  120.        if assigned(fAppOnHelp) then Application.onhelp := fAppOnHelp else Application.onhelp := nil;
  121.   end;
  122.   GLOBAL_HELPROUTER := nil;
  123.   inherited Destroy;
  124. end;
  125.  
  126. function THelpRouter.CurrentForm: TForm;
  127. begin
  128.   if Screen.ActiveForm <> nil
  129.     then result:= Screen.ActiveForm
  130.     else result:= Owner as TForm;
  131. end;
  132.  
  133. procedure THelpRouter.SetHelpType(value: THelpType);
  134. begin
  135.      if value <> fHelpType then
  136.      begin
  137.           fHelpType := value;
  138.           if (fHelpType in [htHTMLhelp,htMixedMode])
  139.             and (not (csDesigning in ComponentState)) then HTMLHelpInstalled;
  140.      end;
  141. end;
  142.  
  143. function THelpRouter.HTMLhelpInstalled: boolean;
  144. begin
  145.   if HHCTRL = 0 then LoadHH;
  146.   result := assigned(HtmlHelpA);
  147. end;
  148.  
  149. function THelpRouter.FindHandle(var returnHelpFile: string): HWND;
  150. var
  151.   CForm: TCustomForm;
  152. begin
  153.    returnHelpFile := Application.helpfile;
  154.    result := Application.handle;
  155.    CForm := CurrentForm;
  156.    if Assigned(CForm) and CForm.HandleAllocated and (CForm.HelpFile <> '') then
  157.    begin
  158.        result := CForm.Handle;
  159.        returnHelpFile := CForm.HelpFile;
  160.    end;
  161.    if fHelpFile <> '' then
  162.    begin
  163.        returnHelpFile := fhelpfile;
  164.        result := Application.handle;
  165.    end;
  166. end;
  167.  
  168. function THelpRouter.OnRouteHelp(Command: Word; Data: Longint; var CallHelp: Boolean): Boolean;
  169. const
  170.    HELP_TAB = 15;
  171. var
  172.    showHTML: boolean;
  173.    rHandle: integer;
  174. begin
  175.    result := false;
  176.    if assigned(fOnHelp) then result := fOnHelp(command, data, callhelp);
  177.    if not callHelp then exit;
  178.    if assigned(fAppOnHelp) then result := fAppOnHelp(command, data, callhelp);
  179.    if not callHelp then exit;
  180.  
  181.    if fShowType = stMain then
  182.      case Command of
  183.      HELP_SETPOPUP_POS: Command := 0;
  184.      HELP_CONTEXTPOPUP: Command := HELP_CONTEXT; //no popup
  185.      end;
  186.  
  187.    aHelpHandle := findHandle(aHelpfile);
  188.  
  189.    showHTML := false;
  190.    case HelpType of
  191.    htHTMLHelp:  showHTML := true;
  192.    htMixedMode: showHTML := (command <> HELP_CONTEXTPOPUP) and
  193.                             (command <> HELP_SETPOPUP_POS);
  194.    end;
  195.  
  196.    if showHTML then
  197.    begin
  198.      if not HTMLhelpInstalled then exit; //result false
  199.  
  200.      rHandle := 0;
  201.      aHelpFile := changefileext(aHelpFile,'.chm');
  202.      case Command of
  203.      HELP_TAB:
  204.        case data of
  205.        0: rHandle := HtmlHelpA(aHelpHandle, pchar(aHelpFile), HH_DISPLAY_TOC, 0);  //show table of contents
  206.        else rHandle := HtmlHelpA(aHelpHandle, pchar(aHelpFile), HH_DISPLAY_INDEX, 0);  //display keyword
  207.        end;
  208.      HELP_FINDER,
  209.      HELP_CONTENTS:
  210.        rHandle := HtmlHelpA(aHelpHandle, pchar(aHelpFile), HH_DISPLAY_TOC, 0);  //show table of contents
  211.      HELP_PARTIALKEY,
  212.      HELP_KEY:
  213.        rHandle := HtmlHelpA(aHelpHandle, pchar(aHelpFile), HH_DISPLAY_INDEX, data);  //display keyword
  214.      HELP_QUIT:
  215.        rHandle := HtmlHelpA(aHelpHandle, nil, HH_CLOSE_ALL, 0);
  216.      HELP_SETPOPUP_POS:
  217.        fPP := SmallPointToPoint(TSmallPoint(Data));
  218.      HELP_CONTEXT:
  219.        rHandle := HtmlHelpA(aHelpHandle, pchar(aHelpFile), HH_HELP_CONTEXT, data);  //display help context
  220.      HELP_CONTEXTPOPUP:
  221.        begin
  222.             if (fPP.x = 0) and (fPP.y = 0) then GetCursorPos(fPP);
  223.             HelpPopup(fPP.x, fPP.y, data, '');
  224.             fPP := point(0,0); //reset;
  225.             CallHelp := false;
  226.             result := true;
  227.             exit;
  228.        end;
  229.      end;
  230.      Result := rHandle <> 0;
  231.    end else
  232.    begin
  233.      if Command <> 0 then Result := WinHelp(aHelpHandle, PChar(changefileext(aHelpFile,'.hlp')), Command, Data)
  234.      else Result := true;
  235.    end;
  236.    CallHelp := false;
  237. end;
  238.  
  239. function THelpRouter.HelpContent: boolean;
  240. begin
  241.    result := application.helpcommand(15, 0);
  242. end;
  243.  
  244. function THelpRouter.ValidateHTMLID(link: string): string;
  245. var
  246.    vli: integer;
  247. begin
  248.       result := '';
  249.       for vli := 1 to length(link) do case link[vli] of
  250.       '\',
  251.       '/',
  252.       '"',
  253.       '|',
  254.       ',',
  255.       '?',
  256.       '┐',
  257.       ':': result := result + '';  //nothing
  258.       ' ',
  259.       '.',
  260.       '%': result := result + '_';
  261.       '>',
  262.       '<': result := result + '~';
  263.       '&',
  264.       '*': result := result + '+';
  265.       '[': result := result + '(';
  266.       ']': result := result + ')';
  267.       'Σ',
  268.       '─': result := result + 'a';
  269.       '÷',
  270.       '╓': result := result + 'o';
  271.       'ⁿ',
  272.       '▄': result := result + 'u';
  273.       '▀': result := result + 's';
  274.       else result := result + link[vli];
  275.       end;
  276. end;
  277.  
  278.  
  279. function THelpRouter.HelpJump(hfile, topicid: string): boolean;
  280. var
  281.    Command: array[0..255] of Char;
  282.    rHandle: integer;
  283.    HID: string;
  284. begin
  285.    result := false;
  286.    aHelpHandle := FindHandle(aHelpFile);
  287.  
  288.    if Hfile <> '' then
  289.    begin
  290.         aHelpFile := HFile;
  291.         aHelpHandle := 0;
  292.    end;
  293.  
  294.    if HelpType in [htHTMLhelp,htMixedMode] then
  295.    begin
  296.      if not HTMLhelpInstalled then exit; //result false
  297.  
  298.      aHelpFile := changefileext(aHelpFile,'.chm');
  299.      rHandle := 0;
  300.      HID := TopicID;
  301.      if HID <> '' then
  302.      begin
  303.           if copy(lowercase(extractfileext(HID)),1,4) <> '.htm' then
  304.           begin
  305.                if fValidateID then HID := ValidateHTMLID(HID);
  306.                HID := HID + '.htm';
  307.           end;
  308.      end;
  309.      if HID <> '' then
  310.      begin
  311.           aHelpFile := aHelpFile + '::/' + HID;
  312.           rHandle := HtmlHelpA(aHelpHandle, pchar(aHelpFile), HH_DISPLAY_TOPIC, 0); //show topic
  313.      end
  314.      else rHandle := HtmlHelpA(aHelpHandle, pchar(aHelpFile), HH_HELP_FINDER, 0);  //show table of contents
  315.      Result := rHandle <> 0;
  316.    end
  317.    else begin
  318.      aHelpfile := changefileext(aHelpFile,'.hlp');
  319.      StrLFmt(Command, SizeOf(Command) - 1, 'JumpID("","%s")', [TopicID]);
  320.      Result := WinHelp(aHelpHandle, PChar(aHelpfile), HELP_CONTENTS, 0);
  321.      if Result then Result := WinHelp(aHelpHandle, PChar(aHelpfile), HELP_COMMAND, Longint(@Command));
  322.    end;
  323. end;
  324.  
  325. function THelpRouter.HelpPopup(X,Y: integer; HelpContext: integer; Text: string): boolean;
  326. var
  327.    CForm: TForm;
  328. begin
  329.    if HTMLhelpInstalled then
  330.    begin
  331.      CForm := CurrentForm;
  332.      with aHH_POPUP do
  333.      begin
  334.           cbStruct := sizeof(aHH_POPUP);
  335.           hInst := 0;
  336.           if Text = '' then idString := HelpContext
  337.                        else idString := 0;
  338.           pszText := PChar(text);
  339.           pt.x := X;
  340.           pt.y := Y;
  341.           clrForeground := -1;
  342.           clrBackground := -1;
  343.           rcMargins.Left := -1;
  344.           rcMargins.Right := -1;
  345.           rcMargins.Top := -1;
  346.           rcMargins.Bottom := -1;
  347.           pszFont := PChar('MS Sans Serif, 8');
  348.      end;
  349.  
  350.      if aHH_POPUP.idString <> 0 then
  351.      begin
  352.           if fCHMPopupTopics = '' then fCHMPopupTopics := 'CSHelp.txt';
  353.           aHelpHandle := FindHandle(aHelpFile);
  354.           aHelpFile := changefileext(aHelpFile,'.chm') + '::/'+fCHMPopupTopics;
  355.           result := HtmlHelpA(aHelpHandle, pchar(aHelpFile), HH_DISPLAY_TEXT_POPUP, longint(@aHH_POPUP)) <> 0;
  356.      end
  357.      else result := HtmlHelpA(CForm.handle, nil, HH_DISPLAY_TEXT_POPUP, longint(@aHH_POPUP)) <> 0;
  358.    end
  359.    else result := false;
  360. end;
  361.  
  362. function THelpRouter.HelpKeyword(keyword: string): boolean;
  363. var
  364.   Command: array[0..255] of Char;
  365. begin
  366.   StrLcopy(Command, pchar(keyword), SizeOf(Command) - 1);
  367.   result := application.helpcommand(HELP_KEY, Longint(@Command));
  368. end;
  369.  
  370. function THelpRouter.HelpKLink(keyword: string): boolean;
  371. var
  372.    Command: array[0..255] of Char;
  373.    rHandle: integer;
  374.    afile: string;
  375. begin
  376.    result := false;
  377.    aHelpHandle := FindHandle(afile);
  378.  
  379.    if HelpType in [htHTMLhelp,htMixedMode] then
  380.    begin
  381.      if not HTMLhelpInstalled then exit; //result false
  382.  
  383.      rHandle := 0;
  384.      aHelpFile := changefileext(afile,'.chm');
  385.      aKeyWord := keyword+#0;
  386.  
  387.      with aHH_AKLINK do
  388.      begin
  389.           cbStruct := sizeof(aHH_AKLINK);
  390.           fReserved := false;
  391.           pszKeywords := pchar(aKeyword);
  392.           pszUrl := '';
  393.           pszMsgText := '';
  394.           pszMsgTitle := '';
  395.           pszMsgWindow := '';
  396.           fIndexOnFail := true;
  397.      end;
  398.      rHandle := HtmlHelpA(aHelpHandle, pchar(aHelpfile), HH_DISPLAY_TOPIC, 0);  //create window
  399.      if rHandle <> 0 then rHandle := HtmlHelpA(aHelphandle, pchar(aHelpfile), HH_KEYWORD_LOOKUP, longint(@aHH_AKLINK));
  400.      Result := rHandle <> 0;
  401.    end
  402.    else begin
  403.      aFile := changefileext(afile,'.hlp');
  404.      StrLFmt(Command, SizeOf(Command) - 1, 'KL("%s",1)', [keyword]);
  405.      Result := WinHelp(aHelpHandle, PChar(afile), HELP_CONTENTS, 0);
  406.      if Result then Result := WinHelp(aHelpHandle, PChar(afile), HELP_COMMAND, Longint(@Command));
  407.    end;
  408. end;
  409.  
  410. function THelpRouter.HelpALink(keyword: string): boolean;
  411. var
  412.    Command: array[0..255] of Char;
  413.    rHandle: integer;
  414.    afile: string;
  415. begin
  416.    result := false;
  417.    aHelpHandle := FindHandle(afile);
  418.  
  419.    if HelpType in [htHTMLhelp,htMixedMode] then
  420.    begin
  421.      if not HTMLhelpInstalled then exit; //result false
  422.  
  423.      rHandle := 0;
  424.      aHelpFile := changefileext(afile,'.chm');
  425.      aKeyWord := keyword+#0;
  426.  
  427.      with aHH_AKLINK do
  428.      begin
  429.           cbStruct := sizeof(aHH_AKLINK);
  430.           fReserved := false;
  431.           pszKeywords := pchar(akeyword);
  432.           pszUrl := '';
  433.           pszMsgText := '';
  434.           pszMsgTitle := '';
  435.           pszMsgWindow := '';
  436.           fIndexOnFail := true;
  437.      end;
  438.      rHandle := HtmlHelpA(aHelpHandle, pchar(aHelpfile), HH_DISPLAY_TOPIC, 0);  //create window
  439.      if rHandle <> 0 then rHandle := HtmlHelpA(aHelphandle, pchar(aHelpfile), HH_ALINK_LOOKUP, longint(@aHH_AKLINK));
  440.      Result := rHandle <> 0;
  441.    end
  442.    else begin
  443.      afile := changefileext(afile,'.hlp');
  444.      StrLFmt(Command, SizeOf(Command) - 1, 'AL("%s",1)', [keyword]);
  445.      Result := WinHelp(aHelpHandle, PChar(afile), HELP_CONTENTS, 0);
  446.      if Result then Result := WinHelp(aHelpHandle, PChar(afile), HELP_COMMAND, Longint(@Command));
  447.    end;
  448. end;
  449.  
  450. end.
  451.